/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.deployment.manager;

import br.com.deployment.entidade.arquivo.Anexo;
import br.com.deployment.entidade.humana.Pessoa;
import br.com.deployment.entidade.registroimovel.Operacao;
import br.com.deployment.entidade.registroimovel.Objeto;
import br.com.deployment.entidade.registroimovel.Imovel;
import br.com.deployment.entidade.localidade.Endereco;
import br.com.deployment.entidade.registroimovel.*;
import br.com.deployment.servico.*;
import br.com.deployment.servicoimpl.ImovelServicoImpl;
import br.com.deployment.util.Caracteres;
import br.com.deployment.util.CoordinateConversion;
import br.com.deployment.util.VOGmapIntersection;
import br.com.deployment.utilitario.Msg;
import br.com.deployment.utilitario.TipoEndereco;
import br.com.deployment.utilitario.TipoLogradouro;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.map.*;
import org.primefaces.model.map.Polygon;

/**
 *
 * @author ronieresousa
 */
@ManagedBean
@ViewScoped
public class ManagerImovel implements Serializable {

    @EJB
    ImovelServico imovelServico;
    @EJB
    OperacaoServico operacaoServico;
    @EJB
    CidadeServico cidadeServico;
    @EJB
    TituloServico tituloServico;
    @EJB
    FolhaServico folhaServico;
    @EJB
    LivroServico livroServico;
    private Transferencia transferencia;
    private Imovel imovel;
    private Endereco endereco;
    private Objeto objeto;
    private boolean regAnterior;
    private Operacao operacao;
    private List<Imovel> selectAutoImovelAnterior;
    private List<GeoRef> lstGeoRef;
    private MapModel polygonModel;
    private MapModel polygonIntesction;
    private VOGmapIntersection GmapIntersection;
    private String imovelAnteriorSemCadastro;
    private String centerMap;
    private String zoomMap;
    private String folhas;

    
    private String convN;
    private String convE;
    private String convZona;
    
    
    @PostConstruct
    public void init() {

        this.transferencia = new Transferencia();
        this.objeto = new Objeto();
        this.imovel = new Imovel();
        this.endereco = new Endereco();
        this.regAnterior = false;
        this.selectAutoImovelAnterior = new ArrayList<Imovel>();
        this.lstGeoRef = new ArrayList<GeoRef>();
        this.polygonModel = new DefaultMapModel();
        this.polygonIntesction = new DefaultMapModel();
        this.centerMap = "-2.9136, -41.7577";
        this.zoomMap = "23";
        
    }

    public void converterCoord(){
        System.err.println("CONVERTENDO COORDENADA");
//        /* EXEMPLO
//        cc.utm2LatLon("24 M 212951 9673551");
//        cc.utm2LatLon("24 M 212951 9673551");
//        */
        String lat = convN;
        String lon = convE;
        String zona = convZona;
        
        try{
            lat = lat.replace(" ", "");
            lon = lon.replace(" ", "");
            if(zona == null){
                zona = "M";
            }

            CoordinateConversion cc = new CoordinateConversion();

            String UTM = lon.toString().substring(0, 2)+" "+zona+" "+lon.toString().substring(2)+ " "+ lat.toString();
            System.err.println("CONVERTENDO COORDENADA: "+UTM);
            lstGeoRef.add(new GeoRef(cc.utm2LatLon(UTM)[0],cc.utm2LatLon(UTM)[1], lon, lat, zona));
            
        }catch(Exception e){
            Msg.messagemError("Valores incorretos");
            
        }
        
    }
    
    
    public VOGmapIntersection getGmapIntersection() {
        return GmapIntersection;
    }

    public String getConvE() {
        return convE;
    }

    public void setConvE(String convE) {
        this.convE = convE;
    }

    public String getConvN() {
        return convN;
    }

    public void setConvN(String convN) {
        this.convN = convN;
    }

    public String getConvZona() {
        return convZona;
    }

    public void setConvZona(String convZona) {
        this.convZona = convZona;
    }

    public String getZoomMap() {
        return zoomMap;
    }

    public void setZoomMap(String zoomMap) {
        this.zoomMap = zoomMap;
    }

    public void setGmapIntersection(VOGmapIntersection GmapIntersection) {
        this.GmapIntersection = GmapIntersection;
    }

    public String getImovelAnteriorSemCadastro() {
        return imovelAnteriorSemCadastro;
    }

    public void setImovelAnteriorSemCadastro(String imovelAnteriorSemCadastro) {
        this.imovelAnteriorSemCadastro = imovelAnteriorSemCadastro;
    }

    public String getCenterMap() {
        return centerMap;
    }

    public void setCenterMap(String centerMap) {
        this.centerMap = centerMap;
    }

    public MapModel getPolygonModel() {
        return polygonModel;
    }

    public void setPolygonModel(MapModel polygonModel) {
        this.polygonModel = polygonModel;
    }

    public List<GeoRef> getLstGeoRef() {
        return lstGeoRef;
    }

    public void setLstGeoRef(List<GeoRef> lstGeoRef) {
        this.lstGeoRef = lstGeoRef;
    }

    public Operacao getOperacao() {
        return operacao;
    }

    public void setOperacao(Operacao operacao) {
        this.operacao = operacao;
    }

    public boolean isRegAnterior() {
        return regAnterior;
    }

    public void setRegAnterior(boolean regAnterior) {
        this.regAnterior = regAnterior;
    }

    public Imovel getImovel() {
        return imovel;
    }

    public void setImovel(Imovel imovel) {
        this.imovel = imovel;
    }

    public Endereco getEndereco() {
        return endereco;
    }

    public void setEndereco(Endereco endereco) {
        this.endereco = endereco;
    }

    public Objeto getObjeto() {
        return objeto;
    }

    public void setObjeto(Objeto objeto) {
        this.objeto = objeto;
    }

    public String getFolhas() {
        return folhas;
    }

    public void setFolhas(String folhas) {
        this.folhas = folhas;
    }
    

    public MapModel getPolygonIntesction() {
        return polygonIntesction;
    }

    public void setPolygonIntesction(MapModel polygonIntesction) {
        this.polygonIntesction = polygonIntesction;
    }

    public VOGmapIntersection getvOGmapIntersection() {
        return GmapIntersection;
    }

    public void setvOGmapIntersection(VOGmapIntersection vOGmapIntersection) {
        this.GmapIntersection = vOGmapIntersection;
    }

    public Transferencia getTransferencia() {
        return transferencia;
    }

    public void setTransferencia(Transferencia transferencia) {
        this.transferencia = transferencia;
    }

    public boolean verificaMap() {
        
            
        try {
            WKTReader reader = new WKTReader(new GeometryFactory());
            String p1 = "POLYGON((";

            if (lstGeoRef.size() >= 3) {
                
                System.err.println("Verifica Map"+lstGeoRef.size());
                
                for (GeoRef gf : lstGeoRef) {
                     if(gf.getLat() != 0){
                        p1 += gf.getLat() + " " + gf.getLng() + ", ";
                     }
                    System.err.println("Coordenadas: " + p1.toString());
                }
                p1 += lstGeoRef.get(0).getLat() + " " + lstGeoRef.get(0).getLng() + " )) ";

                com.vividsolutions.jts.geom.Polygon polygon1 =
                        (com.vividsolutions.jts.geom.Polygon) reader.read(p1);

                List<Imovel> lstI = imovelServico.findAll();
                
                for (Imovel im : lstI) {
                    
                    if (im.getObjeto() != null) {
                        
                        String p2 = "POLYGON((";

                        List<GeoRef> lstGF = im.getObjeto().getGeoReferenciamento();

                        if (lstGF.size() >= 3) {
                            
                            for (GeoRef gf : lstGF) {
                                p2 += gf.getLat() + " " + gf.getLng() + ", ";
                            }
                            
                            p2 += lstGF.get(0).getLat() + " " + lstGF.get(0).getLng() + " ))";

                            com.vividsolutions.jts.geom.Polygon polygon2 = (com.vividsolutions.jts.geom.Polygon) reader.read(p2);

                            if (polygon1.intersects(polygon2)) {
                                if (polygon2.contains(polygon1)) {
                                    interseccao(polygon1, im);
                                }
                                if (polygon1.contains(polygon2)) {
                                    interseccao(polygon2, im);
                                } else {
                                    interseccao(polygon1.intersection(polygon2), im);
                                }

                                return true;
                            }
                        }

                    }
                }
            }else if(lstGeoRef.size() > 1 && lstGeoRef.size() < 3){
                return true;
            }
        } catch (ParseException ex) {
            Logger.getLogger(ImovelServicoImpl.class.getName()).log(Level.SEVERE, null, ex);
            Msg.messagemError("Erro em geolocalização, verifique as coordenadas1");
        } catch(Exception e){
            Msg.messagemError("Erro em geolocalização, verifique as coordenadas");
            return true;
        }
        return false;
    }

    public double calcArea(Polygon pl) throws ParseException {

        WKTReader reader = new WKTReader(new GeometryFactory());

        String p = "POLYGON(( ";
        for (LatLng ll : pl.getPaths()) {
            p += ll.getLat() + " " + ll.getLng() + ", ";
        }
        p += "" + pl.getPaths().get(0).getLat() + " " + pl.getPaths().get(0).getLng() + " )) ";

        com.vividsolutions.jts.geom.Polygon polygonInt =
                (com.vividsolutions.jts.geom.Polygon) reader.read(p);
        System.err.println(polygonInt.getLength() + "LENGTH");
        System.err.println(polygonInt.getBoundary());
        System.err.println(polygonInt.getDimension());
        return polygonInt.getArea();

    }

    public void interseccao(Geometry gmt, Imovel objIm) throws ParseException {

        GmapIntersection = new VOGmapIntersection();
        Polygon polygonInte = new Polygon();
        Polygon orig = new Polygon();
        Polygon imovelConf = new Polygon();

        for (Coordinate c : gmt.getCoordinates()) {
            polygonInte.getPaths().add(new LatLng(c.x, c.y));
        }
        polygonInte.setStrokeColor("#00ff00");
        polygonInte.setFillColor("#00ff00");
        polygonInte.setStrokeOpacity(0.7);
        polygonInte.setFillOpacity(0.7);

        GmapIntersection.setArea(calcArea(polygonInte));
        GmapIntersection.setImovel(objIm);

        for (GeoRef gfi : objIm.getObjeto().getGeoReferenciamento()) {
            imovelConf.getPaths().add(new LatLng(gfi.getLat(), gfi.getLng()));
        }

        imovelConf.setStrokeColor("#d93c3c");
        imovelConf.setFillColor("#d93c3c");
        imovelConf.setStrokeOpacity(0.7);
        imovelConf.setFillOpacity(0.7);
        
        polygonInte.setStrokeOpacity(0.5);
        polygonInte.setFillOpacity(0.5);


        for (GeoRef gr : lstGeoRef) {
            orig.getPaths().add(new LatLng(gr.getLat(), gr.getLng()));
        }

        orig.setStrokeColor("#FF9900");
        orig.setFillColor("#FF9900");
        orig.setStrokeOpacity(0.6);
        orig.setFillOpacity(0.5);

        polygonIntesction.addOverlay(imovelConf);
        polygonIntesction.addOverlay(orig);
        polygonIntesction.addOverlay(polygonInte);


    }

    public void initMap() {
        if(lstGeoRef.size() >= 1){
        polygonModel = new DefaultMapModel();
        Polygon polygon = new Polygon();

        Double centerX = 0D;
        Double centerY = 0D;
        int tam = lstGeoRef.size();
        for (GeoRef geoRef : lstGeoRef) {
            if (geoRef.getLat() != 0.0 && geoRef.getLng() != 0.0) {
                polygon.getPaths().add(new LatLng(geoRef.getLat(), geoRef.getLng()));
                
                Marker marker = new Marker(new LatLng(geoRef.getLat(), geoRef.getLng()));
                polygonModel.addOverlay(marker);
                centerX += geoRef.getLat() / tam;
                centerY += geoRef.getLng() / tam;

            }
        }
        
        if(tam >=4 && tam < 6){
            zoomMap = "18";
        }else if(tam >= 6){
            zoomMap = "14";
        }else if(tam >= 8){
            zoomMap = "12";
        }
        centerMap = lstGeoRef.get(0).getLat() + ", " + lstGeoRef.get(0).getLng();
        
        polygon.setStrokeColor("#FF9900");
        polygon.setFillColor("#FF9900");
        polygon.setStrokeOpacity(0.6);
        polygon.setFillOpacity(0.5);

        polygonModel.addOverlay(polygon);

        for (Marker marker : polygonModel.getMarkers()) {
            marker.setDraggable(true);
        }
        }
    }
    
    public boolean folhasFind(){
        if(imovel.getLivro() != null && folhas != null){
            String[] folha = folhas.split("-");
            for (int i = 0; i < folha.length; i++) {
                
                if(!folhaServico.folhaExiste(Integer.valueOf(folha[i]), imovel.getLivro().getId())){
                    Msg.messagemError("O Livro "+livroServico.find(imovel.getLivro().getId()).getDescricao()+" não possui a página "+folha[i]);
                    return false;
                }
                
            }
        }
        return true;
    }

    public void criar(List<Anexo> lstArquivo) {
        System.err.println("Criando Imovel");
        Caracteres c = new Caracteres();


        if (objeto.getCidade() != null) {
            objeto.setCidade(cidadeServico.find(objeto.getCidade().getCod_cidade()));
            objeto.setEstado(objeto.getCidade().getCod_estado());
        }
        objeto.setCep(c.removecaracter(objeto.getCep()));
        objeto.setAreaAtual(objeto.getAreaOriginal());
        imovel.setObjeto(objeto);
        System.err.println("OPERAÇÃO --- "+operacao);
        imovel.setOperacao(operacao);
        imovel.setAnexo(lstArquivo);

        if (!selectAutoImovelAnterior.isEmpty()) {
            this.imovel.setImovelAnterior(selectAutoImovelAnterior);
        } else if (imovelAnteriorSemCadastro != null) {
            this.imovel.setImovelAnteriorSemCadastro(imovelAnteriorSemCadastro);
        }
        selectAutoImovelAnterior = new ArrayList<Imovel>();

        if (!verificaMap() ) {
            if(livroServico.folhasFind(imovel.getLivro(), folhas)){
                if(lstGeoRef.size() > 1){
                    imovel.getObjeto().setGeoReferenciamento(lstGeoRef);
                }
                imovel.setFolhasString(folhas);
                
                imovelServico.create(imovel, transferencia);
             }else{
                return;
            }
            
        } else {
            Msg.messagemError("Conflito em geoLocalização");
            org.primefaces.context.RequestContext.getCurrentInstance().execute("gmapIntesc.show();");
            return;
        }
    }

    public void reinit() {
        this.imovel = new Imovel();
        this.objeto = new Objeto();
        this.operacao = new Operacao();
        System.err.println("reinit");
    }

    public List<Imovel> completeImovel(String query) {
        List<Imovel> suggestions = new ArrayList<Imovel>();
        List<Imovel> bd = new ArrayList<Imovel>();

        bd = imovelServico.findImovelLimit(10, query);

        for (Imovel p : bd) {
            if (p.getRegistro().startsWith(query)) {
                suggestions.add(p);
            }
        }

        return suggestions;
    }

    public List<Imovel> listarImoveis() {
        return imovelServico.findAll();
    }

    public void transferirImovel(Imovel imovel) {
        redirect("transferirImovel.xhtml");
    }

    public void averbarImovel(Imovel imovel) {
        redirect("averbarImovel.xhtml");
    }

    public void criarImovel() {
        init();
        redirect("criarImovel.xhtml");
    }

    public void pesquisarImovel() {
        redirect("buscarImovel.xhtml");
    }

    public void redirect(String string) {
        try {
            FacesContext context = FacesContext.getCurrentInstance();
            context.getExternalContext().redirect(string);
        } catch (IOException ex) {
            Logger.getLogger(ManagerImovel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void atribuiEndereco(Objeto end) {
        this.objeto = end;
    }

    public void handleSelect(SelectEvent event) {
        Operacao operacaoSelec = (Operacao) event.getObject();
        operacao = operacaoServico.find(operacaoSelec.getId());
        System.err.println("HANDLESELECT OPERACAO IMOVEL"+operacao);

    }

    public SelectItem[] selectItemTipoEndereco() {
        SelectItem[] items = new SelectItem[TipoEndereco.values().length];
        int i = 0;
        for (TipoEndereco tipo : TipoEndereco.values()) {
            items[i++] = new SelectItem(tipo);
        }
        return items;
    }

    public SelectItem[] selectItemTipoLogradouro() {
        SelectItem[] items = new SelectItem[TipoLogradouro.values().length];
        int i = 0;
        for (TipoLogradouro tipo : TipoLogradouro.values()) {
            items[i++] = new SelectItem(tipo);
        }
        return items;
    }

    public void atribui(TipoEndereco tipo) {
//        objeto.setTipo(tipo);
    }
    

    public void handleSelectImovel(SelectEvent event) {
        Imovel imovelHandle = (Imovel) event.getObject();
        selectAutoImovelAnterior.add(imovelServico.find(imovelHandle.getId()));

    }

    public void addGeoRef() {
        this.lstGeoRef.add(new GeoRef());
    }

    public void removeGeoRef(GeoRef gf) {
        this.lstGeoRef.remove(gf);
        initMap();
    }

    //TRANSFERENCIA
    public void handleSelectTransf(SelectEvent event) {
        Titulo titulo = (Titulo) event.getObject();
        transferencia.setTitulo(tituloServico.find(titulo.getId()));
    }

    public void removeListAdquirente(Pessoa pessoa) {
        if (pessoa != null) {
            transferencia.getAdquirente().remove(pessoa);
        }
    }

    public void removeListTransmitente(Pessoa pessoa) {
        if (pessoa != null) {
            transferencia.getTransmitente().remove(pessoa);
        }
    }

    public void selecionaAdquirente(Pessoa pessoa) {
        if (transferencia.getAdquirente() != null) {
            transferencia.getAdquirente().add(pessoa);
        } else {
            List<Pessoa> lstPessoa = new ArrayList<Pessoa>();
            lstPessoa.add(pessoa);
            transferencia.setAdquirente(lstPessoa);
        }
    }

    public void selecionaTransmitente(Pessoa pessoa) {

        if (transferencia.getTransmitente() != null) {
            transferencia.getTransmitente().add(pessoa);

        } else {
            List<Pessoa> lstPessoa = new ArrayList<Pessoa>();
            lstPessoa.add(pessoa);
            transferencia.setTransmitente(lstPessoa);
        }
    }

    public void handleSelectTitulo(SelectEvent event) {
        Titulo titulo = (Titulo) event.getObject();
        transferencia.setTitulo(tituloServico.find(titulo.getId()));
    }
    
    public void handleSelectLivro(SelectEvent event) {
        Livro livro = (Livro) event.getObject();
    }
}
